package com.tian.service.impl;

import com.tian.convert.UserCouponRecordConvertUtil;
import com.tian.dto.coupon.UserActivityCouponPageReqDto;
import com.tian.dto.user.UserCouponAddDto;
import com.tian.dto.user.UserCouponRecordDto;
import com.tian.dto.user.UserCouponRecordListRespDto;
import com.tian.entity.*;
import com.tian.enums.ResultCode;
import com.tian.enums.UserPointRecordTypeEnum;
import com.tian.mapper.ActivityCouponMapper;
import com.tian.mapper.PointsModifyRecordMapper;
import com.tian.mapper.UserActivityCouponMapper;
import com.tian.mapper.UserMapper;
import com.tian.service.ActivityCouponService;
import com.tian.service.UserCouponService;
import com.tian.util.CommonResult;
import com.tian.util.RedisConstantPre;
import com.tian.util.UserCacheUtil;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author tianwc  公众号：java后端技术全栈、面试专栏
 * @version 1.0.0
 * 博客地址：<a href="http://woaijava.cc/">博客地址</a>
 * <p>
 * 用户领取优惠券
 */
@Service("userCouponService")
public class UserCouponServiceImpl implements UserCouponService {
    @Resource
    private UserActivityCouponMapper userActivityCouponMapper;
    @Resource
    private ActivityCouponService activityCouponService;
    @Resource
    private PointsModifyRecordMapper pointsModifyRecordMapper;
    @Resource
    private ActivityCouponMapper activityCouponMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private RedissonClient redissonClient;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CommonResult<Boolean> receive(UserCouponAddDto userCouponAddDto) {

        User user = UserCacheUtil.getUser();

        boolean need = checkCouponNeedLock(userCouponAddDto.getActivityId(), userCouponAddDto.getCouponId());
        //key=前缀+活动id+优惠券id
        String key = RedisConstantPre.USER_COUPON_PRE + userCouponAddDto.getActivityId() + userCouponAddDto.getCouponId();
        if (need) {
            redissonClient.getLock(key).lock();
        }
        try {
            CommonResult<ActivityCoupon> commonResult = activityCouponService.check(userCouponAddDto);
            if (commonResult.getCode() != ResultCode.SUCCESS.getCode()) {
                return CommonResult.failed(commonResult.getMessage());
            }
            ActivityCoupon activityCoupon = commonResult.getData();

            int count = userActivityCouponMapper.countByUserIdAndCouponId(userCouponAddDto.getUserId(), userCouponAddDto.getCouponId());

            if (count >= activityCoupon.getLimitPerUser()) {
                return CommonResult.failed(ResultCode.USER_COUPON_LIMITER);
            }
            if (activityCoupon.getTotalCount() <= activityCoupon.getRemainCount()) {
                return CommonResult.failed(ResultCode.TREMAIN_COUNT_LIMITER);
            }
            redissonClient.getLock(RedisConstantPre.USER_POINT_LOCK_PRE + userCouponAddDto.getUserId()).lock();


            // TODO: 2023/11/14

            /*if (activityCoupon.getPoint() > user.getPoints()) {
                return CommonResult.failed(ResultCode.ACTIVITY_NO_COUPON);
            }
            int point = user.getPoints() - activityCoupon.getPoints();
            user.setPoints(point);*/

            userMapper.updateUser(user);

            UserCouponRecord userCouponRecord = UserCouponRecordConvertUtil.convert(userCouponAddDto);
            UserActivityCoupon userActivityCoupon = new UserActivityCoupon();
            userActivityCoupon.setCouponId(userCouponAddDto.getCouponId());
            userActivityCoupon.setUserId(user.getId());
            userActivityCoupon.setStatus(0);
            userActivityCouponMapper.insert(userActivityCoupon);

            // TODO: 2023/11/14
//            addUserPointRecord(activityCoupon.getPoints(), UserPointRecordTypeEnum.DELETE.getType(), user.getId());
        } finally {
            redissonClient.getLock(RedisConstantPre.USER_POINT_LOCK_PRE + userCouponAddDto.getUserId()).unlock();
            if (need) {
                redissonClient.getLock(key).unlock();
            }
        }
        return CommonResult.success(Boolean.TRUE);
    }

    private boolean checkCouponNeedLock(Integer activityId, Integer couponId) {
        ActivityCoupon activityCoupon = activityCouponMapper.selectByActivityCoupon(activityId, couponId);
        return activityCoupon != null && activityCoupon.getTotalCount() != 0;
    }

    @Override
    public CommonResult<UserCouponRecordListRespDto> list(UserActivityCouponPageReqDto userActivityCouponPageReqDto) {
        UserCouponRecordDto userCouponRecordDto = new UserCouponRecordDto();
        int count = userActivityCouponMapper.count(userActivityCouponPageReqDto);
        if (count == 0) {
            return CommonResult.success();
        }
        List<UserActivityCoupon> userCouponRecordList = userActivityCouponMapper.page(userActivityCouponPageReqDto);

/*        UserCouponRecordListRespDto userCouponRecordListRespDto = new UserCouponRecordListRespDto(userCouponRecordReqDto.getStart(), userCouponRecordReqDto.getPageSize(), count);
        userCouponRecordListRespDto.setList(UserCouponRecordConvertUtil.convert(userCouponRecordList));*/

//        return CommonResult.success(userCouponRecordListRespDto);
        return CommonResult.success();
    }

    private void addUserPointRecord(int point, int type, int userId) {

        PointsModifyRecord pointsModifyRecord = new PointsModifyRecord();
        pointsModifyRecord.setPoints(point);
        pointsModifyRecord.setCreateTime(new Date());
        pointsModifyRecord.setUserId(userId);
        pointsModifyRecord.setType(type);
        pointsModifyRecordMapper.insert(pointsModifyRecord);
    }
}
